﻿using System;
using System.Web;
using System.Web.Script.Serialization;

namespace Social
{
	public class LocalUtils
	{
		public static HttpContext GetHttpContext()
		{
			var hc = HttpContext.Current;
			if (hc == null) 
				throw new ApplicationException("This method is supposed to be called from web application");
			return hc;
		}

		public static string GetFullUrl(string relPath)
		{
			var hc = GetHttpContext();
			return hc.Request.Url.Scheme + "://" + hc.Request.Url.Authority + relPath;
		}

		public static object GetShortenedText(string text, int charsNum)
		{
			if (text.Length<charsNum)
				return text;
			else
			return text.Substring(0, charsNum)+ "...";
		}

        /// <summary>
        /// method for converting a UNIX timestamp to a regular
        /// System.DateTime value 
        /// </summary>
        /// <param name="timestamp">value to be converted</param>
        /// <returns>converted DateTime in string format</returns>
        public static DateTime ConvertTimestamp(double timestamp)
        {
            //create a new DateTime value based on the Unix Epoch
            DateTime converted = new DateTime(1970, 1, 1, 0, 0, 0, 0);

            //add the timestamp to the value
            DateTime newDateTime = converted.AddSeconds(timestamp);

            //return the value in string format
            return newDateTime;
        }

        /// <summary>
        /// This method will count the chars that within a string
        /// </summary>
        /// <param name="value">The string to count his chars</param>
        /// <returns>The number of chars that within the string without whiteSpaces</returns>
        public static int CountChars(string value)
        {
            int result = 0;
            bool lastWasSpace = false;

            foreach (char c in value)
            {
                if (char.IsWhiteSpace(c))
                {
                    // A.
                    // Only count sequential spaces one time.
                    if (lastWasSpace == false)
                    {
                        result++;
                    }
                    lastWasSpace = true;
                }
                else
                {
                    // B.
                    // Count other characters every time.
                    result++;
                    lastWasSpace = false;
                }
            }
            return result;
        }

	}

	public static class Extensions
	{
        public static string ValidateWebsite(this string str)
        {
            if (string.IsNullOrEmpty( str))
                return string.Empty;
            if (str.Substring(0, 7) == "http://")
                return str;
            else
                return "http://" + str;
        }

        public static string GetPartialString(this string s, int length)
        {
            if (s == null)
                return "";
            if (s.Length <= length)
            {
                return s;
            }
            else
            {
                return s.Substring(0, length - 3) + "...";
            }

        }

		public static bool IsNullEmptyOrZero(this string s)
		{
			if (string.IsNullOrEmpty(s) || s == "0")
				return true;
			return false;
		}

		public static int ZeroNulls(this int? num)
		{
			if (!num.HasValue)
				num = 0;
			return num.Value;
		}

		/// <summary>
		/// Returns !string.IsNullOrEmpty on the string specified.
		/// </summary>
		/// <param name="s"></param>
		/// <returns>bool</returns>
		public static bool IsExists(this string s)
		{
			return !string.IsNullOrEmpty(s);
		}

		/// <summary>
		/// Returns true if all the strings in the array are not null or empty.
		/// </summary>
		/// <param name="text"></param>
		/// <returns></returns>
		public static bool IsAllExists(params string[] text)
		{
			bool isAllExist = true;
			foreach (var s in text)
			{
                if (!s.IsExists())
                    return false;
			}
			return isAllExist;
		}

		/// <summary>
		/// Converts datetime to time stamp
		/// </summary>
		/// <param name="date"></param>
		/// <returns></returns>
		public static long ToTimeStamp(this DateTime date)
		{
			DateTime converted = new DateTime(1970, 1, 1, 0, 0, 0, 0);
			return (long)date.Subtract(converted).TotalSeconds;
		}
		public static string Format(this object obj, string format)
		{
			if (obj == null || obj == DBNull.Value)
				return "";
			else return obj.GetType().InvokeMember("ToString", System.Reflection.BindingFlags.InvokeMethod, null, obj, new object[] { format }).ToString();
		}

		public static long ToPostId(this string obj)
		{
			if (obj.Contains("_"))
				obj = obj.Split('_')[1];
			return Convert.ToInt64(obj);
		}

		public static DateTime ToDateTime(this string date)
		{
			return Convert.ToDateTime(date);
		}

        /// <summary>
        /// This method will append to the number passed an ordinal suffix.
        /// e.g. th, st, nd, etc.
        /// </summary>
        /// <param name="number">the number to append to</param>
        /// <returns>The number with his ordinal suffix as string</returns>
        public static string Ordinal(this int number)
        {
            var work = number.ToString();
            if (number == 11 || number == 12 || number == 13)
                return work + "th";
            switch (number % 10)
            {
                case 1: work += "st"; break;
                case 2: work += "nd"; break;
                case 3: work += "rd"; break;
                default: work += "th"; break;
            }
            return work;
        }
        
        /// <summary>
        /// This method will append to the number passed an ordinal suffix.
        /// e.g. th, st, nd, etc.
        /// </summary>
        /// <param name="number">the number to append to</param>
        /// <returns>The number with his ordinal suffix as string</returns>
        public static string Ordinal(this string number)
        {
            var work = Convert.ToInt32(number);
            if (number == "11" || number == "12" || number == "13")
                return number + "th";
            switch (work % 10)
            {
                case 1: number += "st"; break;
                case 2: number += "nd"; break;
                case 3: number += "rd"; break;
                default: number += "th"; break;
            }
            return number;
        }

		//public static int Sum(params object[] objects)
		//{
		//    int sum = 0;
		//    int value;
		//    foreach (var obj in objects)
		//        sum += int.TryParse(obj.ToString(), out value)? value: 0;
		//    return sum;
		//}
	}
    
    public enum ServiceResultOptions
    {
        ServiceValidationFailure,       // Occurs when the request did not comply to the services authentication
        Success,                        // Occurs when the operation succeeded
        SystemException,                // Occurs when a system exception had been thrown during the execution of the requested service method
        ValidationFailure,              // Occurs when a validation performed in the service method returned a validation failure response
        OperationFailure,               // Occurs when the operation did not succeed
        IncorrectParameters,             // Occurs when the parameter passed to the service method where incorrect or incomplete
		DuplicateFailure
	}

    public class ServiceResponse
    {
        public ServiceResultOptions ResultOption { get; set; }
        public string Message { get; set; }

        public virtual void SetException(Exception ex) 
        { 
            this.Message = ex.Message; 
            this.ResultOption = ServiceResultOptions.SystemException; 
        }
        public virtual void SetSuccess()
        {
            this.ResultOption = ServiceResultOptions.Success;
        }
    }

    public class BooleanServiceResponse : ServiceResponse
    {
        public bool Success { get; set; }
    }

    public class ContentServiceResponse<T> : ServiceResponse
    {
        public T Content { get; set; }
    }

    /// <summary>
    /// This attribute is used to represent a string value
    /// for a value in an enum.
    /// </summary>
    public class StringValueAttribute : Attribute
    {

        #region Properties

        /// <summary>
        /// Holds the stringvalue for a value in an enum.
        /// </summary>
        public string StringValue { get; protected set; }

        #endregion

        #region Constructor

        /// <summary>
        /// Constructor used to init a StringValue Attribute
        /// </summary>
        /// <param name="value"></param>
        public StringValueAttribute(string value)
        {
            this.StringValue = value;
        }

        #endregion



    }


	public class JSON
	{
		public static T DeserializeObject<T>(object obj)
		{
			JavaScriptSerializer jss = new JavaScriptSerializer();
			try
			{
				var request = jss.ConvertToType<T>(obj);
				return request;
			}
			catch (Exception ex)
			{
				return default(T);
			}
		}

		public static T DeserializeJSON<T>(string json)
		{
			JavaScriptSerializer jss = new JavaScriptSerializer();
			try
			{
				var request = jss.Deserialize<T>(json);
				return request;
			}
			catch (Exception ex)
			{
				return default(T);
			}
		}
	}


}

//this is a patch to prevent the Extention Atribute missing constructor error
namespace System.Runtime.CompilerServices
{
	public class ExtensionAttribute : Attribute { }
}